﻿// ***********************************************************************************************************************************************************
// * Copyright (c) 2008 Unit Software                                                                                                                        *
// *                                                                                                                                                         *
// * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),      *
// * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,      *
// * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:              *
// *                                                                                                                                                         *
// * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.                          *
// *                                                                                                                                                         *
// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS    *
// * IN THE SOFTWARE.                                                                                                                                        *
// ***********************************************************************************************************************************************************
using System.Collections.Generic;
using System.Data.Linq;

namespace UnitSoftware.LINQ2SQLExtensions
{
    public class DataChanges
    {
        private readonly List<ObjectChangeConflict> _conflicts = new List<ObjectChangeConflict>();
        private readonly List<object> _deletes = new List<object>();
        private readonly List<object> _inserts = new List<object>();
        private readonly List<object> _updates = new List<object>();

        public List<object> Deletes
        {
            get { return _deletes; }
        }

        public List<object> Updates
        {
            get { return _updates; }
        }

        public List<object> Inserts
        {
            get { return _inserts; }
        }

        public List<ObjectChangeConflict> Conflicts
        {
            get { return _conflicts; }
        }

        public List<TEntity> GetInserts<TEntity>() where TEntity : Entity
        {
            return GetTypedList<TEntity>(_inserts);
        }

        public List<TEntity> GetDeletes<TEntity>() where TEntity : Entity
        {
            return GetTypedList<TEntity>(_deletes);
        }

        public List<TEntity> GetUpdates<TEntity>() where TEntity : Entity
        {
            return GetTypedList<TEntity>(_updates);
        }

        private static List<TEntity> GetTypedList<TEntity>(List<object> list) where TEntity : Entity
        {
            var typedList = new List<TEntity>();

            foreach (var obj in list)
                if (obj is TEntity)
                    typedList.Add((TEntity) obj);

            return typedList;
        }

        public List<TEntity> GetDistinctChanges<TEntity>() where TEntity : Entity
        {
            var insertsAndUpdates = new List<TEntity>();

            insertsAndUpdates.AddRange(GetInserts<TEntity>());

            foreach (var update in GetUpdates<TEntity>())
                if (!insertsAndUpdates.Contains(update))
                    insertsAndUpdates.Add(update);

            return insertsAndUpdates;
        }

        internal void AmalgamateExcludingConflicts(DataChanges changes)
        {
            foreach (var delete in changes.Deletes)
                if (!_deletes.Contains(delete))_deletes.Add(delete);

            foreach (var insert in changes.Inserts)
                if (!_inserts.Contains(insert)) _inserts.Add(insert);

            foreach (var update in changes.Updates)
                if (!_updates.Contains(update)) _updates.Add(update);
        }
    }
}